#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sstream>
#include <iostream>

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Output.H>
#include <FL/fl_draw.H>

#include "Game.h"

using namespace std;

void parse_message(string temp_str);

//Holds the elements needed to draw the circles
struct Circle
{
    char p;
    int x;
    int y;

    Circle():p(BLANK), x(0), y(0){}
    Circle(char pp, int xx, int yy):p(pp), x(xx), y(yy){}
};

//Global variables used across the client
char buffer[1024];
bool ai_human = true;
int sockfd;

string sr = "";
string pt = "";
string next_server = "";
string next_port   = "";

vector<Circle> circles;

void send_message(string temp)
{
    bzero(buffer, sizeof(buffer));
    strcpy ( buffer, temp.c_str() );

    int n = 0;
    n = write(sockfd,buffer,strlen(buffer));
    if(n < 0) cout<<"Error writing to sockfd"<<endl;
}

//converts integers to hex character
char to_hex(int num)
{    
    
    if(num < 10)
        return (char)(num + 48);

    return (char)(num + 55);
}

class Grid : public Fl_Box
{
    
    bool black_win;
    bool white_win;
    bool first_read;

    public:
    bool connected;

    //Parses the messages sent from teh server
    void parse_message(string temp_str)
    {
        send_message(temp_str);

        bzero(buffer, sizeof(buffer));
        
        int n = 0;
        //if(first_read)
        //{
            //Needs to read twice after the first move for some reason
        //    n = read(sockfd, buffer, sizeof(buffer));
         //   first_read = false;
        //}
        n = read(sockfd, buffer, sizeof(buffer));

        if(n < 0)
        {
            cout<<"Error reading from socket"<<endl;
            return;
        }

        //convert the buffer to a string to check if there is a winner
        stringstream ss;
        string str;
        ss << buffer;
        ss >> str;

        str = str.substr(0,16);

        if(str == "***BLACK_WINS***")
        {
            black_win = true;
        }
        if(str == "***WHITE_WINS***")
        {
            black_win = true;
        }


        //Cycle through the buffer to find and place the pieces into circles
        circles.clear();

        int i = 0;
        while(!(buffer[i] == ';' && buffer[i+1] == '1' && buffer[i+2] == ' '))
        {
            if(i == 1021) break;
            i++;
        }
        i+=3;

        for(int j = 1; j < 16; j++)//row
        {
            for(int k = 1; k < 16; k++)//column
            {
                if(buffer[i] == WHITE)
                {
                    Circle temp(WHITE,k,j);
                    circles.push_back(temp);
                }

                else if(buffer[i] == BLACK)
                {
                    Circle temp(BLACK,k,j);
                    circles.push_back(temp);
                }
                i+=2;        
            }
            i+=4;
        }
    }
    
    void draw() 
    {
        //0,16,win->w(), win->h()-26
        fl_draw_box(FL_FLAT_BOX, 0, 26, 800, 600-26, FL_DARK2);

    	fl_color(0);
        //draw the grid
        fl_line_style(FL_SOLID, 2);
        for(int i = 0; i < 375; i+=25)
            fl_line(55,55+i,435,55+i);

        for(int i = 0; i < 375; i+=25)
            fl_line(70+i,40,70+i,420);

        //draw black wins
        if(black_win)
        {
            string temp = "***BLACK WINS***";
            fl_draw(temp.c_str(), 450, 150);
        }
        //draw white wins
        if(white_win)
        {
            string temp = "***WHITE WINS***";
            fl_draw(temp.c_str(), 450, 150);
        }

        //draw connected server and port
        if(sr!="" && pt != "")
        {
        	string temp2 = "Connected to " + sr + " port: " + pt;
        	fl_draw(temp2.c_str(), 450, 50);
    	}	

        for(size_t i = 0; i < circles.size(); i++)
        {
            if(circles[i].p == BLACK)
                fl_color(0);
            else
                fl_color(255);

            fl_pie(60+(25*(circles[i].x-1)), 45+(25*(circles[i].y-1)), 20, 20, 0.0, 360.0);
        }
    }

    string add_move(int x, int y)
    {
        // top corner is 70,55
        for(int i = 0; i < 15; i++)
        {
            for(int j = 0; j < 15; j++)
            {
                //if x,y is in this box
                //place black circle
                int corner_x = 70+(j*25);
                int corner_y = 55+(i*25);

                if( x>corner_x-12 && x<corner_x+12 && 
                    y>corner_y-12 && y<corner_y+12)
                {
                    char x_char = to_hex(i+1);
                    char y_char = to_hex(j+1);


                    string temp_str = "";
                    temp_str.append(1,x_char);
                    temp_str.append(1,y_char);
                    return temp_str;

                }
            
            }
        }

        return ""; 
    }

    //handles the mouse clicks
    int handle(int event)
    {

        if(event != FL_PUSH || Fl::event_button() != 1)
            return 0;

        if(!connected)
            return 0;

        //Do nothing someone has won
        if(black_win || white_win)
            return 0;

        int x = Fl::event_x();
        int y = Fl::event_y();

        if(x < 40 || x > 500 || y < 40 || y > 500)
            return 0;

        parse_message(this->add_move(x,y));
        this->redraw();

        return 0;
    };

    Grid(int X,int Y,int W,int H,const char*L=0) : Fl_Box(X,Y,W,H,L), black_win(false),
                                                    white_win(false), first_read(true),
                                                    connected(false) {
        box(FL_FLAT_BOX);
        color(45);
    }
};

Fl_Window *connect_win= new Fl_Window(300,200, "Connection");
Fl_Window *win = new Fl_Window(800,600, "Gomoku Client");
Grid* grid_pointer;
